與其說 Image(映像檔)是 ISO 系統安裝檔或虛擬機快照,不如說 Image 更像是還沒執行的程式碼,跟程式不同的點是它是一個唯獨的檔案,而 Container(容器)是正在執行的程式
Image 可以從雲端儲存庫 pull 下來,或是用 Dockerfile build 出來,也可以從檔案 load 到本地儲存庫
Docker Hub 是一個最受歡迎的雲端儲存庫,我們可以在上面找到要用到的 Image
我們來下載 Nginx 的 Image,這樣就不用再把伺服器軟體安裝在系統上了
https://hub.docker.com/_/nginx
docker pull nginx
如果出現這坨字,表示沒把 Docker 運行起來,Docker 其實是個 Client-Server 架構,平常打指令的 CLI 只是 Client,還會需要一個 Server,也就是 Docker Daemon 才能運作
error during connect: this error may indicate that the docker daemon is not running: Get "http://%2F%2F.%2Fpipe%2Fdocker_engine/v1.24/images/json": open //./pipe/docker_engine: The system cannot find the file specified.
查看現在本地儲存庫有哪些 images
docker images
接著是讓它跑起來,變成 Container,-p
表示的是將內部的 80 port 映射到外部的 8001 port,也就是可以從外部的 8001 port 訪問到內部的 80 port
docker run -p 8001:80 nginx
如果想讓容器跑起來時進到裡面可以加上 -it
參數,如果想讓容器在背景執行可以加上 -d
參數
現在打開瀏覽器應該就可以看到 Nginx 的預設頁面啦
http://localhost:8001/
Ctrl + C 可以終止容器運行,或是開另一個終端機用 docker stop {id or name}
來停止,要重新啟動的話就用 docker start {id or name}
或 docker restart {id or name}
ps 可以查看運行中的容器,加上 -a
則是列出全部,包含運行結束的容器
docker ps -a
要從容器列表中移除容器的話,可以使用 docker rm {id or name}
要移除映像檔的話則是使用 docker rmi {id or name}
現在應該很了解容器怎麼用了吧
Image 有點太單調了我需要一點調味
DockerFile 就像是一個食譜一樣,使用基本的食材再加上一些調味料和擺盤,讓 Image 變得更豐盛美味
我們來把 Nginx 的預設首頁改掉,找個喜歡的資料夾建立以下檔案
html/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<h1 align="center">Hello, Docker!</h1>
</body>
</html>
在 nginx 這個基本映像檔上加上 COPY,將外部的 ./html 複製進去 /usr/share/nginx/html
Dockerfile
FROM nginx
COPY ./html /usr/share/nginx/html
在專案資料夾中使用 docker build,來把 Dockerfile(食譜)變成 Image(料理),加上 -t
可以為它取個名字
docker build -t mynginx .
現在 Image 列表中就能看到我們自己製作的 Image
docker images
把它運行起來看看
docker run -p 8002:80 mynginx
現在再打開瀏覽器應該就可以看到我們自己製作的首頁啦
http://localhost:8001/
一道道料理分開點餐有點麻煩,有沒有超值套餐可以選擇
Docker Compose 就像是一個套餐一樣,點一份套餐就能包含前菜、主食、飲料、點心,只需要一個指令就能同時啟動好幾個容器
我們來做一個 Nginx + PHP-FPM 的套餐吧,找個喜歡的資料夾建立以下檔案
public/index.php
echo "<h1>Hello, Docker Compose!</h1>";
nginx-default.conf
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
root /srv/www/public;
index index.php;
add_header X-Frame-Options "SAMEORIGIN";
add_header X-Content-Type-Options "nosniff";
charset utf-8;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location = /favicon.ico { access_log off; log_not_found off; }
location = /robots.txt { access_log off; log_not_found off; }
error_page 404 /index.php;
location ~ \.php$ {
fastcgi_pass unix:/sock/docker.sock;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
include fastcgi_params;
}
location ~ /\.(?!well-known).* {
deny all;
}
}
php-fpm.conf
[global]
daemonize = no
[www]
listen = /sock/docker.sock
listen.mode = 0666
docker-compose.yml
services:
php-fpm:
image: php:8.2-fpm
container_name: php-fpm
volumes:
- .:/srv/www
- ./php-fpm.conf:/usr/local/etc/php-fpm.d/zz-docker.conf
- sock:/sock
nginx:
image: nginx
container_name: nginx
depends_on:
- php-fpm
ports:
- 80:80
volumes:
- .:/srv/www
- ./nginx-default.conf:/etc/nginx/conf.d/default.conf
- sock:/sock
volumes:
sock:
接著就是用 Docker Composer 來把這個套餐做出來,加上 -d
可以在背景運行
docker composer up
現在再打開瀏覽器應該就可以看到我們自己製作的首頁啦
http://localhost/
設定 volumes(磁區)可以將容器外的目錄或檔案掛載進容器內,就好像是影分身一樣,改裡面的東西 外面的也會改變,改外面的東西 裡面的也會改變,它本質上就是同個東西嘛
因為上述原理,現在可以隨意修改 index.php,不用重新 composer up,Docker 真是個方便好用的工具
另外還有幾個常用的指令
暫停 compose
docker compose stop
繼續執行 compose
docker compose start
重啟 compose
docker compose restart
停止 compose
docker compose down
列出所有 compose
docker compose ls -a
不知不覺就來到最後一天了,看來我太低估了這個題目的複雜程度,本來是想說講完 Docker 就用它來把資料庫建起來,然後讓 Laravel 接上,完成完整版的 E2E Test
不過講不完就算啦,我相信走到這裡你也有能力自己把它完成了,最後大魔王(Docker + Laravel + Database + E2E Test + CI/CD)就交給你討伐啦,再不行的話就來 水球軟體學院 找答案吧,我把寶藏都放在那裡了